diff --git a/apis/apps/v1alpha1/daemonset_types.go b/apis/apps/v1alpha1/daemonset_types.go
index aec3f7df..cfbf05e2 100644
--- a/apis/apps/v1alpha1/daemonset_types.go
+++ b/apis/apps/v1alpha1/daemonset_types.go
@@ -152,6 +152,9 @@ type DaemonSetSpec struct {
 	// The default value is 250
 	BurstReplicas *intstr.IntOrString `json:"burstReplicas,omitempty"`
 
+	// Replicas is the number of desired pods in accordance with the number matching nodes.
+	Replicas *int32 `json:"replicas,omitempty"`
+
 	// The number of old history to retain to allow rollback.
 	// This is a pointer to distinguish between explicit zero and not specified.
 	// Defaults to 10.
@@ -224,6 +227,8 @@ type DaemonSetStatus struct {
 }
 
 // +genclient
+// +genclient:method=GetScale,verb=get,subresource=scale,result=k8s.io/api/autoscaling/v1.Scale
+// +genclient:method=UpdateScale,verb=update,subresource=scale,input=k8s.io/api/autoscaling/v1.Scale,result=k8s.io/api/autoscaling/v1.Scale
 // +k8s:openapi-gen=true
 // +kubebuilder:object:root=true
 // +kubebuilder:subresource:status
diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go
index 5aa934dc..4b0597ff 100644
--- a/apis/apps/v1alpha1/zz_generated.deepcopy.go
+++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go
@@ -948,6 +948,11 @@ func (in *DaemonSetSpec) DeepCopyInto(out *DaemonSetSpec) {
 		*out = new(intstr.IntOrString)
 		**out = **in
 	}
+	if in.Replicas != nil {
+		in, out := &in.Replicas, &out.Replicas
+		*out = new(int32)
+		**out = **in
+	}
 	if in.RevisionHistoryLimit != nil {
 		in, out := &in.RevisionHistoryLimit, &out.RevisionHistoryLimit
 		*out = new(int32)
diff --git a/config/crd/bases/apps.kruise.io_daemonsets.yaml b/config/crd/bases/apps.kruise.io_daemonsets.yaml
index 4ef5581d..a4a55a1c 100644
--- a/config/crd/bases/apps.kruise.io_daemonsets.yaml
+++ b/config/crd/bases/apps.kruise.io_daemonsets.yaml
@@ -159,6 +159,11 @@ spec:
                   available as soon as it is ready).
                 format: int32
                 type: integer
+              replicas:
+                description: Replicas is the number of desired pods in accordance
+                  with the number matching nodes.
+                format: int32
+                type: integer
               revisionHistoryLimit:
                 description: The number of old history to retain to allow rollback.
                   This is a pointer to distinguish between explicit zero and not specified.
diff --git a/pkg/client/clientset/versioned/typed/apps/v1alpha1/daemonset.go b/pkg/client/clientset/versioned/typed/apps/v1alpha1/daemonset.go
index 4ebe457b..ad49ead4 100644
--- a/pkg/client/clientset/versioned/typed/apps/v1alpha1/daemonset.go
+++ b/pkg/client/clientset/versioned/typed/apps/v1alpha1/daemonset.go
@@ -23,6 +23,7 @@ import (
 
 	v1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
 	scheme "github.com/openkruise/kruise/pkg/client/clientset/versioned/scheme"
+	autoscalingv1 "k8s.io/api/autoscaling/v1"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	types "k8s.io/apimachinery/pkg/types"
 	watch "k8s.io/apimachinery/pkg/watch"
@@ -46,6 +47,9 @@ type DaemonSetInterface interface {
 	List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.DaemonSetList, error)
 	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
 	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.DaemonSet, err error)
+	GetScale(ctx context.Context, daemonSetName string, options v1.GetOptions) (*autoscalingv1.Scale, error)
+	UpdateScale(ctx context.Context, daemonSetName string, scale *autoscalingv1.Scale, opts v1.UpdateOptions) (*autoscalingv1.Scale, error)
+
 	DaemonSetExpansion
 }
 
@@ -192,3 +196,32 @@ func (c *daemonSets) Patch(ctx context.Context, name string, pt types.PatchType,
 		Into(result)
 	return
 }
+
+// GetScale takes name of the daemonSet, and returns the corresponding autoscalingv1.Scale object, and an error if there is any.
+func (c *daemonSets) GetScale(ctx context.Context, daemonSetName string, options v1.GetOptions) (result *autoscalingv1.Scale, err error) {
+	result = &autoscalingv1.Scale{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("daemonsets").
+		Name(daemonSetName).
+		SubResource("scale").
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// UpdateScale takes the top resource name and the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any.
+func (c *daemonSets) UpdateScale(ctx context.Context, daemonSetName string, scale *autoscalingv1.Scale, opts v1.UpdateOptions) (result *autoscalingv1.Scale, err error) {
+	result = &autoscalingv1.Scale{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("daemonsets").
+		Name(daemonSetName).
+		SubResource("scale").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(scale).
+		Do(ctx).
+		Into(result)
+	return
+}
diff --git a/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_daemonset.go b/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_daemonset.go
index ea7633fe..b8b479da 100644
--- a/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_daemonset.go
+++ b/pkg/client/clientset/versioned/typed/apps/v1alpha1/fake/fake_daemonset.go
@@ -21,6 +21,7 @@ import (
 	"context"
 
 	v1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
+	autoscalingv1 "k8s.io/api/autoscaling/v1"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	labels "k8s.io/apimachinery/pkg/labels"
 	schema "k8s.io/apimachinery/pkg/runtime/schema"
@@ -139,3 +140,25 @@ func (c *FakeDaemonSets) Patch(ctx context.Context, name string, pt types.PatchT
 	}
 	return obj.(*v1alpha1.DaemonSet), err
 }
+
+// GetScale takes name of the daemonSet, and returns the corresponding scale object, and an error if there is any.
+func (c *FakeDaemonSets) GetScale(ctx context.Context, daemonSetName string, options v1.GetOptions) (result *autoscalingv1.Scale, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewGetSubresourceAction(daemonsetsResource, c.ns, "scale", daemonSetName), &autoscalingv1.Scale{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*autoscalingv1.Scale), err
+}
+
+// UpdateScale takes the representation of a scale and updates it. Returns the server's representation of the scale, and an error, if there is any.
+func (c *FakeDaemonSets) UpdateScale(ctx context.Context, daemonSetName string, scale *autoscalingv1.Scale, opts v1.UpdateOptions) (result *autoscalingv1.Scale, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateSubresourceAction(daemonsetsResource, "scale", c.ns, scale), &autoscalingv1.Scale{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*autoscalingv1.Scale), err
+}
diff --git a/pkg/controller/daemonset/daemonset_controller.go b/pkg/controller/daemonset/daemonset_controller.go
index 3de1446b..0e1f5efb 100644
--- a/pkg/controller/daemonset/daemonset_controller.go
+++ b/pkg/controller/daemonset/daemonset_controller.go
@@ -496,7 +496,7 @@ func NewPod(ds *appsv1alpha1.DaemonSet, nodeName string) *corev1.Pod {
 	// newPod.Spec.NodeName = nodeName
 
 	// Added default tolerations for DaemonSet pods.
-	util.AddOrUpdateDaemonPodTolerations(&newPod.Spec)
+	// util.AddOrUpdateDaemonPodTolerations(&newPod.Spec)
 
 	newPodForDSCache.Store(ds.UID, &newPodForDS{generation: ds.Generation, pod: newPod})
 	return newPod
@@ -551,6 +551,11 @@ func (dsc *ReconcileDaemonSet) updateDaemonSetStatus(ds *appsv1alpha1.DaemonSet,
 		return fmt.Errorf("error storing status for DaemonSet %v: %v", ds.Name, err)
 	}
 
+	err = dsc.updateDaemonSetReplicas(ds, desiredNumberScheduled)
+	if err != nil {
+		return fmt.Errorf("error updating DaemonSet %v replicas: %v", ds.Name, err)
+	}
+
 	// Resync the DaemonSet after MinReadySeconds as a last line of defense to guard against clock-skew.
 	if ds.Spec.MinReadySeconds >= 0 && numberReady != numberAvailable {
 		durationStore.Push(keyFunc(ds), time.Duration(ds.Spec.MinReadySeconds)*time.Second)
@@ -558,6 +563,94 @@ func (dsc *ReconcileDaemonSet) updateDaemonSetStatus(ds *appsv1alpha1.DaemonSet,
 	return nil
 }
 
+func (dsc *ReconcileDaemonSet) getEligibleNodesCount(ds *appsv1alpha1.DaemonSet) (int32, error) {
+	// if the nodeSelector is set - use it to calculate the number of nodes possible to host the daemonset's pods
+	if len(ds.Spec.Template.Spec.NodeSelector) > 0 {
+		nodeCount, err := dsc.kubeClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{LabelSelector: labels.SelectorFromSet(ds.Spec.Template.Spec.NodeSelector).String()})
+		if err != nil {
+			return 0, err
+		}
+		return int32(len(nodeCount.Items)), nil
+	}
+
+	// if there is no nodeSelector in the spec - count the number by using nodeShouldRunDaemonPod againts each node
+	nodeList, err := dsc.nodeLister.List(labels.Everything())
+	if err != nil {
+		return 0, fmt.Errorf("couldn't get list of nodes when calculating the number of eligible nodes %#v: %v", ds, err)
+	}
+
+	var count int32
+	for _, node := range nodeList {
+		if shouldRun, _ := nodeShouldRunDaemonPod(node, ds, true); shouldRun {
+			count += 1
+		}
+	}
+	return count, nil
+}
+
+func (dsc *ReconcileDaemonSet) updateDaemonSetReplicas(ds *appsv1alpha1.DaemonSet, desiredNumberScheduled int) error {
+	var nodeCount int32
+	var err error
+	nodeCount, err = dsc.getEligibleNodesCount(ds)
+	if err != nil {
+		return err
+	}
+
+	// if there are more nodes than Desired (cordoned and drained nodes)
+	// we need to resync DaemonSet after some time in case the cordoned/drained nodes get deleted
+	if nodeCount > int32(desiredNumberScheduled) {
+		klog.Infof("Have to reconcile DaemonSet %s/%s in 60 seconds because there are more replicas available (possibly some nodes are cordoned or have intolerable taints) than desired: %d", ds.Namespace, ds.Name, nodeCount)
+		durationStore.Push(keyFunc(ds), time.Duration(60)*time.Second)
+	}
+
+	if ds.Spec.Replicas != nil && *ds.Spec.Replicas == nodeCount {
+		return nil
+	}
+
+	dsClient := dsc.kruiseClient.AppsV1alpha1().DaemonSets(ds.Namespace)
+	policyClient := dsc.kubeClient.PolicyV1().PodDisruptionBudgets(ds.Namespace)
+
+	return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
+		scale, err := dsClient.GetScale(context.TODO(), ds.Name, metav1.GetOptions{})
+		if err != nil {
+			klog.Errorf("Couldn't get scale for DaemonSet %s/%s: %v", ds.Namespace, ds.Name, err)
+			return err
+		}
+
+		newScale := *scale
+		newScale.Spec.Replicas = nodeCount
+		_, err = dsClient.UpdateScale(context.TODO(), ds.Name, &newScale, metav1.UpdateOptions{})
+		if err != nil {
+			klog.Errorf("Couldn't scale DaemonSet %s/%s to %d replicas: %v", ds.Namespace, ds.Name, nodeCount, err)
+			return err
+		}
+		klog.Infof("Updated DaemonSet %s/%s replicas from %d to %d", ds.Namespace, ds.Name, *ds.Spec.Replicas, nodeCount)
+
+		if *ds.Spec.Replicas > nodeCount {
+			pdb, err := policyClient.Get(context.TODO(), ds.Name, metav1.GetOptions{})
+			if err != nil {
+				klog.Errorf("Couldn't get relevant PodDisruptionBudget for DaemonSet %s/%s: %v", ds.Namespace, ds.Name, err)
+				return err
+			}
+			toUpdate := pdb.DeepCopy()
+
+			if toUpdate.Status.ExpectedPods > newScale.Spec.Replicas {
+				klog.Infof("Updating relevant PodDisruptionBudget %s/%s", ds.Namespace, ds.Name)
+				toUpdate.Status.ExpectedPods = newScale.Spec.Replicas
+
+				_, err = policyClient.UpdateStatus(context.TODO(), toUpdate, metav1.UpdateOptions{})
+				if err != nil {
+					klog.Errorf("Couldn't update relevant PodDisruptionBudget status for DaemonSet %s/%s: %v", ds.Namespace, ds.Name, err)
+					return err
+				}
+				klog.Infof("Updated relevant PodDisruptionBudget %s/%s with expected pods %d", ds.Namespace, ds.Name, nodeCount)
+				return nil
+			}
+		}
+		return nil
+	})
+}
+
 func (dsc *ReconcileDaemonSet) storeDaemonSetStatus(ds *appsv1alpha1.DaemonSet, desiredNumberScheduled, currentNumberScheduled, numberMisscheduled, numberReady, updatedNumberScheduled, numberAvailable, numberUnavailable int, updateObservedGen bool, hash string) error {
 	if int(ds.Status.DesiredNumberScheduled) == desiredNumberScheduled &&
 		int(ds.Status.CurrentNumberScheduled) == currentNumberScheduled &&
diff --git a/pkg/controller/daemonset/daemonset_event_handler.go b/pkg/controller/daemonset/daemonset_event_handler.go
index 26a33f3d..68c5ec35 100644
--- a/pkg/controller/daemonset/daemonset_event_handler.go
+++ b/pkg/controller/daemonset/daemonset_event_handler.go
@@ -284,6 +284,23 @@ func (e *nodeEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimitin
 }
 
 func (e *nodeEventHandler) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) {
+	dsList := &appsv1alpha1.DaemonSetList{}
+	err := e.reader.List(context.TODO(), dsList)
+	if err != nil {
+		klog.V(4).Infof("Error enqueueing daemon sets: %v", err)
+		return
+	}
+
+	node := evt.Object.(*v1.Node)
+	for i := range dsList.Items {
+		ds := &dsList.Items[i]
+		if shouldSchedule, _ := nodeShouldRunDaemonPod(node, ds); shouldSchedule {
+			q.Add(reconcile.Request{NamespacedName: types.NamespacedName{
+				Name:      ds.GetName(),
+				Namespace: ds.GetNamespace(),
+			}})
+		}
+	}
 }
 
 func (e *nodeEventHandler) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) {
diff --git a/pkg/controller/daemonset/daemonset_util.go b/pkg/controller/daemonset/daemonset_util.go
index 420188f0..91911fbe 100644
--- a/pkg/controller/daemonset/daemonset_util.go
+++ b/pkg/controller/daemonset/daemonset_util.go
@@ -98,8 +98,16 @@ func nodeInSameCondition(old []corev1.NodeCondition, cur []corev1.NodeCondition)
 //   - shouldContinueRunning:
 //     Returns true when a daemonset should continue running on a node if a daemonset pod is already
 //     running on that node.
-func nodeShouldRunDaemonPod(node *corev1.Node, ds *appsv1alpha1.DaemonSet) (bool, bool) {
-	pod := NewPod(ds, node.Name)
+func nodeShouldRunDaemonPod(node *corev1.Node, ds *appsv1alpha1.DaemonSet, countReplicasFlag ...bool) (bool, bool) {
+	var pod *corev1.Pod
+	// add standard demonset tolerations if countReplicasFlag isn't empty
+	if len(countReplicasFlag) > 0 {
+		pod = &corev1.Pod{Spec: ds.Spec.Template.Spec, ObjectMeta: ds.Spec.Template.ObjectMeta}
+		pod.Namespace = ds.Namespace
+		util.AddOrUpdateDaemonPodTolerations(&pod.Spec)
+	} else {
+		pod = NewPod(ds, node.Name)
+	}
 
 	// If the daemon set specifies a node name, check that it matches with node.Name.
 	if !(ds.Spec.Template.Spec.NodeName == "" || ds.Spec.Template.Spec.NodeName == node.Name) {
